﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace Hids.Classes.AttackSignatures.PacketTests
{
    /// <summary>
    /// This class holds the Properties and Methods used to test a packet for a regular expression
    /// </summary>
    public class Pcre : PacketTest
    {
        #region Public Properties

        /// <summary>
        /// The regular expression tester to use to look for a match in the packet
        /// </summary>
        public Regex ExpressionToTest;

        /// <summary>
        /// Whether to test from the beginning of the packet(false) or the from the last search result(true)
        /// </summary>
        public bool Relative = true;

        #endregion

        #region Constructors

        /// <summary>
        /// This Constructor creates a Pcre class from the passed in properties
        /// </summary>
        public Pcre(string expressionToTest, bool relative)
        {
            ExpressionToTest = new Regex(expressionToTest);
            Relative = relative;
        }

        /// <summary>
        /// This class creats an Pcre class from an XmlAttributeCollection.  Valid attributes and their values:
        /// ExpressionToTest:  perl compatible regular expression
        /// Relative:  boolean
        /// </summary>
        /// <param name="attributes"></param>
        public Pcre(XmlAttributeCollection attributes)
        {
            foreach (XmlAttribute attribute in attributes)
            {
                switch (attribute.Name)
                {
                    case "ExpressionToTest":
                        ExpressionToTest = new Regex(attribute.Value);
                        break;
                    case "Relative":
                        Relative = bool.Parse(attribute.Value);
                        break;
                    default:
                        throw new ApplicationException("Unknown attribute for content:  " + attribute.Name);
                }
            }

            if (ExpressionToTest == null)
                throw new ApplicationException("ExpressionToTest required for a Pcre test");
        }

        #endregion

        #region Public Methods
        
        /// <summary>
        /// Tests a array of bytes against a regular expression starting at a certain point if the Pcre test is relative
        /// </summary>
        /// <param name="payload">An array of bytes to test the regular expression against</param>
        /// <param name="lastSearchOffset">The offset to begin testing against the regular expression
        /// <returns>Whether or not the regular expression found a match in the passed in array of bytes</returns>
        public bool RegularExpressionTest(byte [] payload, int lastSearchOffset)
        {
            string payloadString = "";
            foreach (byte byteToCheck in payload)
                payloadString += Convert.ToChar(byteToCheck); //convert the byte array into a string

            bool result;
            if (Relative)//test the byte string against the regular expression
                result = ExpressionToTest.IsMatch(payloadString, lastSearchOffset);
            else
                result = ExpressionToTest.IsMatch(payloadString);
            return result;
        }

        #endregion
    }
}
